/**
  ******************************************************************************
  * <h2><center>&copy; COPYRIGHT 2013 SBOCK Enterprises LLC.</center></h2>
  * @file    sbock.c 
  * @author  SBOCK Team
  * @version V0.0.0
  * @date    10-April-2013
  * @brief   Main program body.                        
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, Embest SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT
  * OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
  * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
  * CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/

#include <includes.h>
#include <touch_Detect.h>
#include <LCD_SETUP.h>

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define LED_DLYCOUNT_MAX     500
#define LED_DLYCOUNT_MIN     50
#define LED_DLYCOUNT_STEP    50
#define NUM_OF_TASKS	     7
#define ADC3_DR_ADDRESS      ((uint32_t)0x4001224C)

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static  OS_STK          App_TaskStartStk[APP_TASK_START_STK_SIZE];
static  OS_STK	        TempSensor_TaskStartStk[TEMP_SENSOR_TASK_START_STK_SIZE];
static  OS_STK		IncrementTime_TaskStartStk[IncrementTime_TASK_START_STK_SIZE];
static  OS_STK          LCD_TaskStartStk[LCD_TASK_START_STK_SIZE];
static  OS_STK          App_TaskKbdStk[APP_TASK_KBD_STK_SIZE];
static  CPU_INT16U      led_dly_cout = 100;
EXTI_InitTypeDef   EXTI_InitStructure;

__IO uint16_t ADC3ConvertedValue = 0;


/*       mailbox    */
OS_EVENT* lcdBox;
OS_EVENT* tempBox;

/* Private function prototypes -----------------------------------------------*/
static  void  App_TaskCreate       (void);
static  void  App_EventCreate      (void);
static  void  App_TaskStart        (void  *p_arg);
static  void  TempSensor_TaskStart (void  *p_arg);
static  void  IncrementTime_TaskStart	   (void  *p_arg);
static  void  LCD_TaskStart        (void  *p_arg);
static  void  App_TaskKbd          (void  *p_arg);
static  void  ADCConfig            (void);

/* Private functions ---------------------------------------------------------*/
/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */

int  main (void)
{
    CPU_INT08U  os_err;
    /* Disable all ints until we are ready to accept them. */
    BSP_IntDisAll();                                            
    /* Initialize "uC/OS-II, The Real-Time Kernel".*/
    OSInit();          
    /*  Mailbox   */
    lcdBox=OSMboxCreate((void *)0);
    tempBox = OSMboxCreate((void *)0);
    /* Create the start task.*/
    os_err = OSTaskCreateExt((void (*)(void *)) App_TaskStart,  
                             (void          * ) 0,
                             (OS_STK        * )&App_TaskStartStk[APP_TASK_START_STK_SIZE - 1],
                             (INT8U           ) APP_TASK_START_PRIO,
                             (INT16U          ) APP_TASK_START_PRIO,
                             (OS_STK        * )&App_TaskStartStk[0],
                             (INT32U          ) APP_TASK_START_STK_SIZE,
                             (void          * )0,
                             (INT16U          )(OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK));

#if (OS_TASK_NAME_SIZE >= 11)
    OSTaskNameSet(APP_TASK_START_PRIO, (CPU_INT08U *)"Start Task", &os_err);
#endif
    /* Start multitasking (i.e. give control to uC/OS-II).*/
    OSStart();                                                  

    return (0);
}

/**
  * @brief  The startup task.  The uC/OS-II ticker should only be initialize 
  *         once multitasking starts.
  * @param  p_arg  Argument passed to 'App_TaskStart()' by 'OSTaskCreate()'.
  * @retval None
  */
static  void  App_TaskStart (void *p_arg)
{
  (void)p_arg;
  /* Initialize BSP functions. */
  BSP_Init();                                    
  /* Initialize the SysTick. */	
  OS_CPU_SysTickInit();                                       

#if (OS_TASK_STAT_EN > 0)
  /* Determine CPU capacity. */
  OSStatInit();                                               
#endif
  /* Create application events. */
  App_EventCreate();                                          
  /* Create application tasks. */
  App_TaskCreate();  	
  LCD_Setup_Init();
  LCD_ScreenSetup();
 
  while (DEF_TRUE) 
  {
    OSTimeDlyHMSM(0, 0, 0, 250);
  }
}

static void LCD_TaskStart (void *p_arg)
{
  (void)p_arg;
 
  void *msg;
  
 
  while (DEF_TRUE) {
    msg=OSMboxAccept(lcdBox);
    if(msg != (void*)0)
    {
      configBluetooth((char *)msg);
    }
    msg=OSMboxAccept(tempBox);
    if(msg != (void*)0)
    {
      setInsideTemp(*((int *)msg));
      drawTemp();
    }
    touchDetect();
    OSTimeDlyHMSM(0, 0, 0, 50);
  }
}

static  void  TempSensor_TaskStart (void *p_arg)
{
  (void)p_arg; 

  float ADC3VoltageMV = 0.0;
  float temperature = 0;
 
  
  float average=23; 
  int temp;
  uint16_t count=0;
  ADCConfig();
  ADC_SoftwareStartConv(ADC3);
  
  while (DEF_TRUE) 
  {
    ADC3VoltageMV = (float)ADC3ConvertedValue * 0.06;
    temperature= ADC3VoltageMV;
    //temperature = (int16_t)tempCelsius;
    average=(average*0.9)+(temperature*0.1);

    if(++count%1000 == 0)
    {
      average = (average*(1.8)) + 32;
      temp=(int)average;
      OSMboxPost(tempBox, (void *)&temp);
      count=0;
    }
    OSTimeDlyHMSM(0, 0, 0, 50);
  }
}

static  void  IncrementTime_TaskStart (void *p_arg)
{
  (void)p_arg;      
  
  setTime('1', '2', '0', '0', 0);
  drawTime();
  while (DEF_TRUE) 
  {
    incrementTime();
    if(isAlarm()==1)
    {
      isOnAlarm();
    }
    OSTimeDlyHMSM(0, 1, 0, 0);  
    
  }
}

static void ADCConfig(void)
{
  ADC_InitTypeDef       ADC_InitStructure;
  ADC_CommonInitTypeDef ADC_CommonInitStructure;
  DMA_InitTypeDef       DMA_InitStructure;
  GPIO_InitTypeDef      GPIO_InitStructure;

  /* Enable ADC3, DMA2 and GPIO clocks ****************************************/
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);

  /* DMA2 Stream0 channel0 configuration **************************************/
  DMA_InitStructure.DMA_Channel = DMA_Channel_2;  
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC3ConvertedValue;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
  DMA_InitStructure.DMA_BufferSize = 1;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(DMA2_Stream0, &DMA_InitStructure);
  DMA_Cmd(DMA2_Stream0, ENABLE);

  /* Configure ADC3 Channel12 pin as analog input ******************************/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  /* ADC Common Init **********************************************************/
  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
  ADC_CommonInit(&ADC_CommonInitStructure);

  /* ADC3 Init ****************************************************************/
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfConversion = 1;
  ADC_Init(ADC3, &ADC_InitStructure);

  /* ADC3 regular channel12 configuration *************************************/
  ADC_RegularChannelConfig(ADC3, ADC_Channel_12, 1, ADC_SampleTime_3Cycles);

 /* Enable DMA request after last transfer (Single-ADC mode) */
  ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);

  /* Enable ADC3 DMA */
  ADC_DMACmd(ADC3, ENABLE);

  /* Enable ADC3 */
  ADC_Cmd(ADC3, ENABLE);
}

/**
  * @brief  Create the application events.
  * @param  None
  * @retval None
  */
static  void  App_EventCreate (void)
{

}

/**
  * @brief  Create the application tasks.
  * @param  None
  * @retval None
  */
static  void  App_TaskCreate (void)
{
	  int i = 0;
    CPU_INT08U  os_err[NUM_OF_TASKS];

    os_err[i] = OSTaskCreateExt((void (*)(void *)) App_TaskKbd,
                             (void          * ) 0,
                             (OS_STK        * )&App_TaskKbdStk[APP_TASK_KBD_STK_SIZE - 1],
                             (INT8U           ) APP_TASK_KBD_PRIO,
                             (INT16U          ) APP_TASK_KBD_PRIO,
                             (OS_STK        * )&App_TaskKbdStk[0],
                             (INT32U          ) APP_TASK_KBD_STK_SIZE,
                             (void          * ) 0,
                             (INT16U          )(OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK));
#if (OS_TASK_NAME_SIZE >= 9)
    OSTaskNameSet(APP_TASK_KBD_PRIO, "Keyboard", &os_err[i]);
#endif
	   i++;
	
		 os_err[i] = OSTaskCreateExt((void (*)(void *)) TempSensor_TaskStart,  
                             (void          * ) 0,
                             (OS_STK        * )&TempSensor_TaskStartStk[TEMP_SENSOR_TASK_START_STK_SIZE - 1],
                             (INT8U           ) TEMP_SENSOR_TASK_START_PRIO,
                             (INT16U          ) TEMP_SENSOR_TASK_START_PRIO,
                             (OS_STK        * )&TempSensor_TaskStartStk[0],
                             (INT32U          ) TEMP_SENSOR_TASK_START_STK_SIZE,
                             (void          * )0,
                             (INT16U          )(OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK));

#if (OS_TASK_NAME_SIZE >= 9)
    OSTaskNameSet(TEMP_SENSOR_TASK_START_PRIO, "TempSensor", &os_err[i]);
#endif
		i++;
		
                  os_err[i] = OSTaskCreateExt((void (*)(void *)) IncrementTime_TaskStart,  
                             (void          * ) 0,
                             (OS_STK        * )&IncrementTime_TaskStartStk[IncrementTime_TASK_START_STK_SIZE - 1],
                             (INT8U           ) IncrementTime_TASK_START_PRIO,
                             (INT16U          ) IncrementTime_TASK_START_PRIO,
                             (OS_STK        * )&IncrementTime_TaskStartStk[0],
                             (INT32U          ) IncrementTime_TASK_START_STK_SIZE,
                             (void          * )0,
                             (INT16U          )(OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK));

#if (OS_TASK_NAME_SIZE >= 9)
    OSTaskNameSet(IncrementTime_TASK_START_PRIO, "IncrementTime", &os_err[i]);
#endif
		i++;
                		 os_err[i] = OSTaskCreateExt((void (*)(void *)) LCD_TaskStart,  
                             (void          * ) 0,
                             (OS_STK        * )&LCD_TaskStartStk[LCD_TASK_START_STK_SIZE - 1],
                             (INT8U           ) LCD_TASK_START_PRIO,
                             (INT16U          ) LCD_TASK_START_PRIO,
                             (OS_STK        * )&LCD_TaskStartStk[0],
                             (INT32U          ) LCD_TASK_START_STK_SIZE,
                             (void          * )0,
                             (INT16U          )(OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK));

#if (OS_TASK_NAME_SIZE >= 9)
    OSTaskNameSet(LCD_TASK_START_PRIO, "LCD", &os_err[i]);
#endif
		i++;
}

/*    ISR for Bluetooth Serial    */
void USART6_IRQHandler(void){
  static char received_string[21];
   if( USART_GetITStatus(EVAL_COM1, USART_IT_RXNE) ){

		static uint8_t cnt = 0; // this counter is used to determine the string length
		int t = EVAL_COM1->DR; // the character from the USART1 data register is saved in t
                
		/* check if the received character is not the LF character (used to determine end of string) 
		 * or the if the maximum string length has been been reached 
		 */
		if( (t != 0x0)){ 
			received_string[cnt] = t;
			cnt++;
		}
		else{ // otherwise reset the character counter and print the received string
			cnt = 0;
			//configBluetooth(received_string);
                        OSMboxPost(lcdBox, (void *)&received_string[0]);
		}
	}
}
/**
  * @brief  Monitor the state of the push buttons and passes messages to AppTaskUserIF()
  * @param  p_arg  Argument passed to 'App_TaskKbd()' by 'OSTaskCreate()'.
  * @retval None
  */
static  void  App_TaskKbd (void *p_arg)
{
  CPU_BOOLEAN  b1_prev;
  CPU_BOOLEAN  b1;


  (void)p_arg;

  b1_prev = DEF_TRUE;

  while (DEF_TRUE) 
  {
    b1 = STM_EVAL_PBGetState(BUTTON_USER);

    if ((b1 == DEF_FALSE) && (b1_prev == DEF_TRUE)) {
      led_dly_cout += LED_DLYCOUNT_STEP;
      if (led_dly_cout >= LED_DLYCOUNT_MAX) {
        led_dly_cout = LED_DLYCOUNT_MIN;
      }
      b1_prev = b1;
    }

    if ((b1 == DEF_TRUE) && (b1_prev==DEF_FALSE)) {
      b1_prev = DEF_TRUE;		
    }
    OSTimeDlyHMSM(0, 0, 0, 20);
  }
}

#if (OS_APP_HOOKS_EN > 0)
/**
  * @brief  This function is called when a task is created.
  * @param  ptcb  is a pointer to the task control block of the task being created.
  * @retval None
  */
void  App_TaskCreateHook (OS_TCB *ptcb)
{

}

/**
  * @brief  This function is called when a task is deleted.
  * @param  ptcb  is a pointer to the task control block of the task being deleted.
  * @retval None
  */
void  App_TaskDelHook (OS_TCB *ptcb)
{
    (void)ptcb;
}

/**
  * @brief  This function is called by OSTaskIdleHook(), which is called by the 
  *         idle task.  This hook has been added to allow you to do such things 
  *         as STOP the CPU to conserve power.
  * @param  None
  * @retval None
  */
#if OS_VERSION >= 251
void  App_TaskIdleHook (void)
{
}
#endif

/**
  * @brief  This function is called by OSTaskStatHook(), which is called every 
  *         second by uC/OS-II's statistics task.  This allows your application 
  *         to add functionality to the statistics task.
  * @param  None
  * @retval None
  */
void  App_TaskStatHook (void)
{
}

/**
  * @brief  This function is called when a task switch is performed.  This 
  *         allows you to perform other operations during a context switch.
  * @param  None
  * @retval None
  */
#if OS_TASK_SW_HOOK_EN > 0
void  App_TaskSwHook (void)
{

}
#endif

/**
  * @brief  This function is called by OSTCBInitHook(), which is called by 
  *         OS_TCBInit() after setting up most of the TCB.
  * @param  ptcb is a pointer to the TCB of the task being created.
  * @retval None
  */
#if OS_VERSION >= 204
void  App_TCBInitHook (OS_TCB *ptcb)
{
    (void)ptcb;
}
#endif

/**
  * @brief  This function is called every tick.
  * @param  None
  * @retval None
  */
#if OS_TIME_TICK_HOOK_EN > 0
void  App_TimeTickHook (void)
{

}
#endif
#endif

/**
  * @brief  This function is called if a task accidentally returns.  In other words,
  *         a task should either be an infinite loop or delete itself when done.
  * @param  ptcb  is a pointer to the task control block of the task that is returning.
  * @retval None
  */
#if OS_VERSION >= 289
void  App_TaskReturnHook (OS_TCB  *ptcb)
{
    (void)ptcb;
}
#endif
/**
  * @brief  assert failed function.
  * @param  None
  * @retval None
  */
void assert_failed(char* file, int line)
{
	
}




/******************** COPYRIGHT 2012 Embest Tech. Co., Ltd.*****END OF FILE****/
